package com.sc.nft.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.EcologyPoolPrizeDao;
import com.sc.nft.dao.EcologyPoolRedPackDao;
import com.sc.nft.dao.EcologyPoolRedPackReceiveDao;
import com.sc.nft.dto.EcologyPoolIncreasePointsDTO;
import com.sc.nft.dto.OpenRedPackMessageDTO;
import com.sc.nft.entity.EcologyPoolPrize;
import com.sc.nft.entity.EcologyPoolRedPack;
import com.sc.nft.entity.EcologyPoolRedPackReceive;
import com.sc.nft.entity.dto.EcologyPoolRedPackReceiveDO;
import com.sc.nft.entity.vo.EcologyPoolRedPackReceiveVO;
import com.sc.nft.enums.EcologyPoolLinkTypeEnum;
import com.sc.nft.enums.EcologyPoolOperationTypeEnum;
import com.sc.nft.enums.EcologyPoolPrizeBindTypeEnum;
import com.sc.nft.enums.EcologyPoolTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.EcologyPoolRedPackReceiveService;
import com.sc.nft.service.EcologyPoolService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * 品牌红包领取记录服务接口实现
 *
 * @author jinpinhai
 * @since 2024-08-10 11:40:15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class EcologyPoolRedPackReceiveServiceImpl implements EcologyPoolRedPackReceiveService {
    private final EcologyPoolRedPackReceiveDao ecologyPoolRedpackReceiveDao;
    private final EcologyPoolRedPackDao ecologyPoolRedPackDao;
    private final EcologyPoolService ecologyPoolService;
    private final EcologyPoolPrizeDao ecologyPoolPrizeDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void distributeConsumptionPoints(OpenRedPackMessageDTO openRedPackMessageDTO) {
        EcologyPoolRedPackReceive redPackReceive = ecologyPoolRedpackReceiveDao.getById(openRedPackMessageDTO.getReceiveId());
        if (Objects.isNull(redPackReceive)) {
            log.error("红包领取记录不存在{}", openRedPackMessageDTO);
            return;
        }
        if (redPackReceive.getStatus() == Boolean.TRUE) {
            log.error("红包已经发放{}", openRedPackMessageDTO);
            return;
        }
        BigDecimal receiveRewardNumber = redPackReceive.getReceiveRewardNumber();
        EcologyPoolRedPack redPack = ecologyPoolRedPackDao.getById(redPackReceive.getEcologyPoolRedPackId());
        EcologyPoolIncreasePointsDTO build = EcologyPoolIncreasePointsDTO.builder()
                .linkCount(receiveRewardNumber)
                .linkType(EcologyPoolLinkTypeEnum.POINTS)

                .daoId(redPack.getDaoId())
                .poolType(EcologyPoolTypeEnum.ACCOUNT)
                .userId(redPackReceive.getUserId())

                .sourcePoolType(EcologyPoolTypeEnum.RED_PACK)
                .sourceDaoId(redPack.getDaoId())
                .sourceRelationId(redPackReceive.getId())

                .operationType(EcologyPoolOperationTypeEnum.PLUS)
                .transactionUuid(IdUtil.simpleUUID())
                .activeOperatorName(EcologyPoolTypeEnum.RED_PACK.name())
                .passiveOperatorName(EcologyPoolTypeEnum.ACCOUNT.name())
                .build();

        ecologyPoolService.increasePoints(build);

        EcologyPoolPrize prize = ecologyPoolPrizeDao.getPrizeById(redPack.getId(), EcologyPoolPrizeBindTypeEnum.RED_PACK, EcologyPoolLinkTypeEnum.POINTS);
        //扣减数据库
        int count = ecologyPoolPrizeDao.deductionRedEnvelopes(prize.getId(), receiveRewardNumber, prize.getVersion());
        if (count <= 0) {
            throw new GlobalRunTimeException("红包扣减失败!");
        }
        //更新发放状态
        boolean update = ecologyPoolRedpackReceiveDao.updateSendStatus(redPackReceive.getId());
        if (!update) {
            throw new GlobalRunTimeException("红包发放状态更新异常");
        }
    }

    @Override
    public Page<EcologyPoolRedPackReceive> redPackParticipatePage(Long userId, Long daoId, Integer pageNo, Integer pageNum) {
        return ecologyPoolRedpackReceiveDao.redPackParticipatePage(userId, daoId, pageNo, pageNum);
    }

    @Override
    public IPage<EcologyPoolRedPackReceiveVO> daoRedPackReceivePage(Integer pageNo, Integer pageNum, Long daoRedPackId, String userTel) {
        Page<EcologyPoolRedPackReceiveDO> ecologyPoolRedPackReceiveDOPage = ecologyPoolRedpackReceiveDao.receivePage(pageNo, pageNum, daoRedPackId, userTel);
        return ecologyPoolRedPackReceiveDOPage.convert(EcologyPoolRedPackReceiveServiceImpl::getEcologyPoolRedPackReceiveVO);
    }

    @Override
    public void saveRedPackReceive(EcologyPoolRedPackReceive redPackReceive) {
        boolean save = ecologyPoolRedpackReceiveDao.save(redPackReceive);
        if (!save) {
            throw new GlobalRunTimeException("保存领取记录失败");
        }
    }

    @Override
    public int countUserReceive(Long userId, Long redPackId) {
        List<EcologyPoolRedPackReceive> list = ecologyPoolRedpackReceiveDao.countUserReceive(userId, redPackId);
        return list.size();
    }

    @Override
    public int countReceive(Long redPackId) {
        List<EcologyPoolRedPackReceive> list = ecologyPoolRedpackReceiveDao.countUserReceive(null, redPackId);
        return list.size();
    }

    @Override
    public BigDecimal sumReceive(Long redPackId) {
        List<EcologyPoolRedPackReceive> ecologyPoolRedPackReceives = ecologyPoolRedpackReceiveDao.countUserReceive(null, redPackId);
        return ecologyPoolRedPackReceives.stream().map(EcologyPoolRedPackReceive::getReceiveRewardNumber).reduce(BigDecimal.ZERO, BigDecimal::add);
    }


    private static EcologyPoolRedPackReceiveVO getEcologyPoolRedPackReceiveVO(EcologyPoolRedPackReceiveDO ecologyPoolRedPackReceive) {
        EcologyPoolRedPackReceiveVO ecologyPoolRedPackReceiveVO = new EcologyPoolRedPackReceiveVO();
        ecologyPoolRedPackReceiveVO.setUserTel(ecologyPoolRedPackReceive.getUserTel());
        ecologyPoolRedPackReceiveVO.setReceiveReward(EcologyPoolLinkTypeEnum.POINTS.getDesc() + "*" + ecologyPoolRedPackReceive.getReceiveRewardNumber());
        ecologyPoolRedPackReceiveVO.setCreateTime(ecologyPoolRedPackReceive.getCreateTime());
        ecologyPoolRedPackReceiveVO.setNickName(ecologyPoolRedPackReceive.getNickName());
        return ecologyPoolRedPackReceiveVO;
    }

}